//
//  Drumset.h
//  rockband-drums-wii
//
//  Created by Sid Stamm on 8/6/09.
// rockband-drums-wii: enables software synth for Wii-compatible RockBand2 drums
// Copyright (C) 2009  Sid Stamm <sidstamm@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.



#import <Cocoa/Cocoa.h>
#include <IOKit/hid/IOHIDLib.h>

#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h> //for AUGraph


#define kOurVendorID        0x1bad
#define kOurProductID        0x3110
//-guitar #define kOurProductID        0x3010

// for more note IDs see: 
// http://en.wikipedia.org/wiki/General_MIDI#Percussion_notes
#define kRedDrumNoteDefault         38 /* snare */
#define kYellowDrumNoteDefault      42 /* closed hi-hat */
//#define kBlueDrumNoteDefault      46 /* open hi-hat */
#define kBlueDrumNoteDefault        59 /* ride symbol */
#define kGreenDrumNoteDefault       49 /* crash symbol */
#define kPedalNoteDefault           36 /* base 1 */

#define kMidiChannelDefault         9 /* channel 9 (MIDI 10) is percussion */

#define kMidiMessage_ControlChange       0xB
#define kMidiMessage_ProgramChange       0xC
#define kMidiMessage_BankMSBControl      0
#define kMidiMessage_BankLSBControl      32
#define kMidiMessage_NoteOn              0x9

// how the drums sound (program is basically the instrument)
#define kDrumVoiceProgram               1

/** These cookies are for HID device stuff */
typedef struct cookie_struct
{
    IOHIDElementCookie gXAxisCookie;
    IOHIDElementCookie gRedDrumCookie;
    IOHIDElementCookie gYellowDrumCookie;
    IOHIDElementCookie gBlueDrumCookie;
    IOHIDElementCookie gGreenDrumCookie;
    IOHIDElementCookie gPedalCookie;
} *cookie_struct_t;

/** Enumerates each drum on the physical pad */
typedef enum drum_index {
    RED_DRUM    = 0x01,
    YELLOW_DRUM = 0x02,
    BLUE_DRUM   = 0x04,
    GREEN_DRUM  = 0x08,
    PEDAL_DRUM  = 0x10
} drum_index_t;


@interface Drumset : NSObject {
    cookie_struct_t cookies;
    IOHIDQueueInterface **hidQueue;
    
    int redDrumMidiNote;
    int yellowDrumMidiNote;
    int blueDrumMidiNote;
    int greenDrumMidiNote;
    int pedalMidiNote;
    
    int midiChannel;
    
    id listenerObj;
    SEL listenerSel;
    
    bool usingSoftwareSynth;
    AUGraph outGraph;
    AudioUnit outSynth;
    
    // Model data
    float yellow_drum_value;
    float red_drum_value;
    float blue_drum_value;
    float green_drum_value;
    float pedal_drum_value;
}

// define getters and setters  "@synthesize" does the defs in the impl file
@property(readwrite) float  yellow_drum_value, 
                            red_drum_value, 
                            blue_drum_value, 
                            green_drum_value, 
                            pedal_drum_value;
@property(readonly) id      listenerObj;
@property(readonly) SEL     listenerSel;

-(int) getMidiNote:(drum_index_t)drum;
-(void) setMidiNote:(int)note forDrum:(drum_index_t)drum;

// Locates a HID drumset in the IORegistry and returns the interface
+(IOHIDDeviceInterface**) findHIDDrumset;

-(IOHIDQueueInterface**) getQueue;
-(cookie_struct_t) getHidCookies;

-(void)setListener:(id)obj selector:(SEL)s;

-(void)processDrumState:(BOOL)isOn forHIDCookie:(IOHIDElementCookie)cookieValue;
-(void)processDrumHit:(drum_index_t)index;
-(void)sendMidiHit:(int)note onChannel:(int)channel;
-(void)setupSoftwareSynth;
-(void)teardownSoftwareSynth;

-(id)initWithDeviceInterface:(IOHIDDeviceInterface**)deviceInterface;
-(void)setupQueueCallbackOnInterface:(IOHIDDeviceInterface **)deviceInterface;
-(void)testQueueCallback;
-(void)teardownQueueCallback;

@end
